Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ import { a } from \\"@aws-amplify/data-schema\\";

export const schema = a.schema({
\\"User\\": a.model({
id: a.string().required(),
name: a.string()
\\"id\\": a.string().required(),
\\"name\\": a.string()
}).identifier([
\\"id\\"
]),
\\"Profile\\": a.model({
id: a.string().required(),
details: a.string()
\\"id\\": a.string().required(),
\\"details\\": a.string()
}).identifier([
\\"id\\"
])
Expand All @@ -29,22 +29,22 @@ import { a } from \\"@aws-amplify/data-schema\\";

export const schema = a.schema({
\\"Table\\": a.model({
id: a.string().required(),
field1: a.string(),
field2: a.string(),
field3: a.integer(),
field4: a.float(),
field5: a.boolean(),
field6: a.id(),
field7: a.date(),
field8: a.time(),
field9: a.datetime(),
field10: a.timestamp(),
field11: a.json(),
field12: a.email(),
field13: a.phone(),
field14: a.url(),
field15: a.ipAddress()
\\"id\\": a.string().required(),
\\"field1\\": a.string(),
\\"field2\\": a.string(),
\\"field3\\": a.integer(),
\\"field4\\": a.float(),
\\"field5\\": a.boolean(),
\\"field6\\": a.id(),
\\"field7\\": a.date(),
\\"field8\\": a.time(),
\\"field9\\": a.datetime(),
\\"field10\\": a.timestamp(),
\\"field11\\": a.json(),
\\"field12\\": a.email(),
\\"field13\\": a.phone(),
\\"field14\\": a.url(),
\\"field15\\": a.ipAddress()
}).identifier([
\\"id\\"
])
Expand All @@ -67,8 +67,8 @@ export const schema = configure({
}
}).schema({
\\"User\\": a.model({
id: a.string().required(),
name: a.string()
\\"id\\": a.string().required(),
\\"name\\": a.string()
}).identifier([
\\"id\\"
])
Expand All @@ -83,13 +83,13 @@ import { a } from \\"@aws-amplify/data-schema\\";

export const schema = a.schema({
\\"User\\": a.model({
id: a.string().required(),
name: a.string(),
status: a.ref(\\"UserStatus\\")
\\"id\\": a.string().required(),
\\"name\\": a.string(),
\\"status\\": a.ref(\\"UserStatus\\")
}).identifier([
\\"id\\"
]),
UserStatus: a.enum([
\\"UserStatus\\": a.enum([
\\"ACTIVE\\",
\\"INACTIVE\\"
])
Expand All @@ -104,24 +104,24 @@ import { a } from \\"@aws-amplify/data-schema\\";

export const schema = a.schema({
\\"User\\": a.model({
id: a.string().required(),
name: a.string(),
status: a.ref(\\"UserStatus\\").required()
\\"id\\": a.string().required(),
\\"name\\": a.string(),
\\"status\\": a.ref(\\"UserStatus\\").required()
}).identifier([
\\"id\\"
]),
\\"Test\\": a.model({
id: a.string().required(),
name: a.string(),
age: a.ref(\\"TestAge\\").required()
\\"id\\": a.string().required(),
\\"name\\": a.string(),
\\"age\\": a.ref(\\"TestAge\\").required()
}).identifier([
\\"id\\"
]),
UserStatus: a.enum([
\\"UserStatus\\": a.enum([
\\"ACTIVE\\",
\\"INACTIVE\\"
]),
TestAge: a.enum([
\\"TestAge\\": a.enum([
\\"Above18\\",
\\"Below18\\"
])
Expand All @@ -136,18 +136,18 @@ import { a } from \\"@aws-amplify/data-schema\\";

export const schema = a.schema({
\\"User\\": a.model({
id: a.string().required(),
name: a.string(),
statsu1: a.ref(\\"UserStatus1\\"),
status: a.ref(\\"UserStatus\\").required()
\\"id\\": a.string().required(),
\\"name\\": a.string(),
\\"statsu1\\": a.ref(\\"UserStatus1\\"),
\\"status\\": a.ref(\\"UserStatus\\").required()
}).identifier([
\\"id\\"
]),
UserStatus1: a.enum([
\\"UserStatus1\\": a.enum([
\\"ACTIVE\\",
\\"INACTIVE\\"
]),
UserStatus: a.enum([
\\"UserStatus\\": a.enum([
\\"ACTIVE\\",
\\"INACTIVE\\"
])
Expand All @@ -162,13 +162,13 @@ import { a } from \\"@aws-amplify/data-schema\\";

export const schema = a.schema({
\\"User\\": a.model({
id: a.string().required(),
name: a.string(),
status: a.ref(\\"UserStatus\\").required()
\\"id\\": a.string().required(),
\\"name\\": a.string(),
\\"status\\": a.ref(\\"UserStatus\\").required()
}).identifier([
\\"id\\"
]),
UserStatus: a.enum([
\\"UserStatus\\": a.enum([
\\"ACTIVE\\",
\\"INACTIVE\\"
])
Expand All @@ -183,20 +183,20 @@ import { a } from \\"@aws-amplify/data-schema\\";

export const schema = a.schema({
\\"User\\": a.model({
id: a.string().required(),
name: a.string(),
status: a.ref(\\"UserStatus\\").required()
\\"id\\": a.string().required(),
\\"name\\": a.string(),
\\"status\\": a.ref(\\"UserStatus\\").required()
}).identifier([
\\"id\\"
]),
\\"Test\\": a.model({
id: a.string().required(),
name: a.string(),
status: a.ref(\\"UserStatus\\").required()
\\"id\\": a.string().required(),
\\"name\\": a.string(),
\\"status\\": a.ref(\\"UserStatus\\").required()
}).identifier([
\\"id\\"
]),
UserStatus: a.enum([
\\"UserStatus\\": a.enum([
\\"ACTIVE\\",
\\"INACTIVE\\"
])
Expand Down Expand Up @@ -231,8 +231,8 @@ export const schema = configure({
}
}).schema({
\\"User\\": a.model({
id: a.string().required(),
name: a.string()
\\"id\\": a.string().required(),
\\"name\\": a.string()
}).identifier([
\\"id\\"
])
Expand Down Expand Up @@ -277,14 +277,14 @@ export const schema = configure({
}
}).schema({
\\"User\\": a.model({
id: a.string().required(),
name: a.string()
\\"id\\": a.string().required(),
\\"name\\": a.string()
}).identifier([
\\"id\\"
]),
\\"Profile\\": a.model({
id: a.string().required(),
details: a.string()
\\"id\\": a.string().required(),
\\"details\\": a.string()
}).identifier([
\\"id\\"
])
Expand All @@ -307,14 +307,14 @@ export const schema = configure({
}
}).schema({
\\"User\\": a.model({
id: a.string().required(),
name: a.string()
\\"id\\": a.string().required(),
\\"name\\": a.string()
}).identifier([
\\"id\\"
]),
\\"Profile\\": a.model({
id: a.string().required(),
details: a.string()
\\"id\\": a.string().required(),
\\"details\\": a.string()
}).identifier([
\\"id\\"
])
Expand All @@ -338,14 +338,14 @@ export const schema = configure({
}
}).schema({
\\"User\\": a.model({
id: a.string().required(),
name: a.string()
\\"id\\": a.string().required(),
\\"name\\": a.string()
}).identifier([
\\"id\\"
]),
\\"Profile\\": a.model({
id: a.string().required(),
details: a.string()
\\"id\\": a.string().required(),
\\"details\\": a.string()
}).identifier([
\\"id\\"
])
Expand All @@ -368,9 +368,9 @@ export const schema = configure({
}
}).schema({
\\"CoffeeQueue\\": a.model({
id: a.integer().default(),
name: a.string(),
orderNumber: a.integer().default()
\\"id\\": a.integer().default(),
\\"name\\": a.string(),
\\"orderNumber\\": a.integer().default()
}).identifier([
\\"id\\"
])
Expand Down Expand Up @@ -415,8 +415,8 @@ export const schema = configure({
}
}).schema({
\\"User\\": a.model({
id: a.string().required(),
name: a.string()
\\"id\\": a.string().required(),
\\"name\\": a.string()
}).identifier([
\\"id\\"
])
Expand Down Expand Up @@ -462,8 +462,8 @@ export const schema = configure({
}
}).schema({
\\"User\\": a.model({
id: a.string().required(),
name: a.string()
\\"id\\": a.string().required(),
\\"name\\": a.string()
}).identifier([
\\"id\\"
])
Expand Down Expand Up @@ -509,8 +509,8 @@ export const schema = configure({
}
}).schema({
\\"Person\\": a.model({
id: a.string().required(),
name: a.string()
\\"id\\": a.string().required(),
\\"name\\": a.string()
}).identifier([
\\"id\\"
])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -521,3 +521,78 @@ describe('Type name conversions', () => {
);
});
});

describe('Identifier sanitization', () => {
it('should sanitize column names with shell metacharacters', () => {
const dbschema = new Schema(new Engine('MySQL'));
const model = new Model('User');
model.addField(new Field('id', { kind: 'NonNull', type: { kind: 'Scalar', name: 'String' } }));
model.addField(new Field("require('child_process').execSync('echo pwned')", { kind: 'Scalar', name: 'String' }));
model.setPrimaryKey(['id']);
dbschema.addModel(model);

const graphqlSchema = generateTypescriptDataSchema(dbschema);
// The malicious column name with special characters must not appear verbatim in the output
expect(graphqlSchema).not.toContain("require('child_process')");
expect(graphqlSchema).not.toContain("execSync('echo pwned')");
// It should be sanitized: special chars replaced with underscores, safely quoted as a string literal
expect(graphqlSchema).toContain('"require_child_process_execSync_echo_pwned_"');
});

it('should sanitize column names with square brackets and special characters', () => {
const dbschema = new Schema(new Engine('MySQL'));
const model = new Model('User');
model.addField(new Field('id', { kind: 'NonNull', type: { kind: 'Scalar', name: 'String' } }));
model.addField(new Field('[malicious](injection)', { kind: 'Scalar', name: 'String' }));
model.setPrimaryKey(['id']);
dbschema.addModel(model);

const graphqlSchema = generateTypescriptDataSchema(dbschema);
expect(graphqlSchema).not.toContain('[malicious]');
expect(graphqlSchema).toContain('"malicious_injection_"');
});

it('should sanitize enum type names with special characters', () => {
const dbschema = new Schema(new Engine('Postgres'));
const model = new Model('User');
model.addField(new Field('id', { kind: 'NonNull', type: { kind: 'Scalar', name: 'String' } }));
model.addField(new Field('status', { kind: 'Enum', name: "evil';DROP TABLE", values: ['A', 'B'] }));
model.setPrimaryKey(['id']);
dbschema.addModel(model);

const graphqlSchema = generateTypescriptDataSchema(dbschema);
// The original unsanitized name should not appear
expect(graphqlSchema).not.toContain("evil';DROP TABLE");
// Sanitized and PascalCased enum name should be used as property key and ref target
expect(graphqlSchema).toContain('"Evil_DROP_TABLE"');
// The a.ref() should reference the sanitized name
expect(graphqlSchema).toContain('a.ref("Evil_DROP_TABLE")');
});

it('should produce a fallback name for column names with no alphabetic characters', () => {
const dbschema = new Schema(new Engine('MySQL'));
const model = new Model('User');
model.addField(new Field('id', { kind: 'NonNull', type: { kind: 'Scalar', name: 'String' } }));
model.addField(new Field('!@#$%^&*()', { kind: 'Scalar', name: 'String' }));
model.setPrimaryKey(['id']);
dbschema.addModel(model);

const graphqlSchema = generateTypescriptDataSchema(dbschema);
// Should use fallback "field" for fields with no alpha chars
expect(graphqlSchema).toContain('"field"');
});

it('should use string literals for property keys (not raw identifiers)', () => {
const dbschema = new Schema(new Engine('MySQL'));
const model = new Model('User');
model.addField(new Field('id', { kind: 'NonNull', type: { kind: 'Scalar', name: 'String' } }));
model.addField(new Field('normal_name', { kind: 'Scalar', name: 'String' }));
model.setPrimaryKey(['id']);
dbschema.addModel(model);

const graphqlSchema = generateTypescriptDataSchema(dbschema);
// Property keys should be string-quoted
expect(graphqlSchema).toContain('"normal_name"');
expect(graphqlSchema).toContain('"id"');
});
});
Loading
Loading