Security News
GitHub Removes Malicious Pull Requests Targeting Open Source Repositories
GitHub removed 27 malicious pull requests attempting to inject harmful code across multiple open source repositories, in another round of low-effort attacks.
Serialize and sanitize JSON data using TypeScript.
Serializing data sent from the webserver to the client shouldn't be hard. If you're already using TypeScript, you have everything you need. Scrubbr will use your TypeScript types to deeply transform and sanitize your data.
npm i -S scrubbr
// schema.ts
type UserList = {
users: User[];
};
type User = {
name: string;
image: string;
};
import Scrubbr from 'scrubbr';
// Load the typescript schema file
// PERFORMANCE NOTE: this is a synchronous call! Load early and cache to a shared variable.
const scrubbr = new Scrubbr('./schema.ts');
async function api() {
const data = getUsers();
// Serialize the data based on the UserList type defined in schema.ts
return await scrubbr.serialize('UserList', data);
}
// Raw unsanitized data
function getUsers() {
return {
users: [
{
name: 'John Doe',
image: 'http://i.pravatar.cc/300',
email: 'donotspam@me.com',
password: 'xxxsecretxxx',
},
],
};
}
{
"users": [
{
"name": "John Doe",
"image": "http://i.pravatar.cc/300"
}
]
}
You can define additional functions for custom serializations.
Type serializer functions are called every time a matching TypeScript type is encountered.
For example, if you want to use another type to serialize a logged-in user:
import Scrubbr, { useType } from 'scrubbr';
// Called every time scrubbr finds a User type object
scrubbr.addTypeSerializer('User', (data, state) => {
// `context` is a value you pass to scrubbr.serialize (see below)
if (data.id === state.context.loggedInUserId) {
return useType('UserPrivileged');
}
// You can manually transform the data here
return data;
});
// Context can be anything you want
const context = {
loggedInUserId: 10,
};
const serialized = await scrubbr.serialize('PostList', data, context);
This serializer is called at each node of the data object, regardless of type. It's called a path serializer because you'll use the state.path
value to determine which node you're serializing.
In this example we want to convert every createdAt
date value to the local timezone.
import moment from 'moment-timezone';
import Scrubbr, { useType } from 'scrubbr';
// Convert date-like strings from UTC to local time
scrubbr.addPathSerializer((data, state) => {
const path = state.path;
if (path.match(/\.createdAt$/)) {
return moment(data).tz(state.context.timezone).format();
}
return data;
});
const context = {
timezone: 'America/Los_Angeles',
};
const serialized = await scrubbr.serialize('PostList', data, context);
It's easy to try it yourself with the included example in example/index.ts
. Just clone this repo, install the dependencies (npm install
) and then run the example app with:
npm run example
To optimize startup time, you can save the schema object scrubbr uses internally to disk during your build step and then load it directly when you initialize scrubbr. Internally, scrubbr uses the ts-json-schema-generator library to convert TypeScript to a JSON schema file. NOTE: you cannot load any JSON schema file into scrubbr, it needs to follow the conventions of ts-json-schema-generator.
Build
npx ts-json-schema-generator -f ./tsconfig.json -e all -p ./schema.ts -o ./dist/schema.json
Runtime code
import Scrubbr, { JSONSchemaDefinitions } from 'scrubbr';
// Set resolveJsonModule to true in your tsconfig, otherwise use require()
import * as schema from './schema.json';
const scrubbr = new Scrubbr(schema as JSONSchemaDefinitions);
For the sake of performance and simplicity, scrubber does not perform a schema validation step (it outputs data, not validates). However, under the hood scrubbr converts TypeScript to JSONSchema (via the great ts-json-schema-generator package). So you can easily use ajv to validate the serialized object.
import Ajv from 'ajv';
import Scrubbr from 'scrubbr';
const scrubbr = new Scrubbr('./schema.ts');
async function main() {
// Serialize
const output = await scrubbr.serialize('UserList', data);
const jsonSchema = scrubbr.getSchema();
// Validate
const ajv = new Ajv();
const schemaValidator = ajv.compile(jsonSchema);
const isValid = schemaValidator(output);
if (!isValid) {
console.error(schemaValidator.errors);
}
}
If scrubbr is not returning the data you're expecting, the first place to look is at the internal schema definitions:
console.log(scrubbr.getSchema());
This is a JSON schema that is created from your TypeScript file.
Next look at the schema definition for the TypeScript type you're trying to serialize to.
// return scrubbr.serialize('UserList', data);
console.log(scrubbr.getSchemaForType('UserList'));
Verify that this returns a JSON Schema object and that it contains the properties you want serialized.
Enable debug logging:
import Scrubbr, { LogLevel } from 'scrubbr';
const scrubbr = new Scrubbr('./schema.ts', { logLevel: LogLevel.DEBUG });
Scrubbr can also nest the logs to make it easier to read:
const scrubbr = new Scrubbr('./schema.ts', {
logLevel: LogLevel.DEBUG,
logNesting: true,
});
And you can even enter the indent string to use for each level of nesting:
const scrubbr = new Scrubbr('./schema.ts', {
logLevel: LogLevel.DEBUG,
logNesting: '~~>',
});
FAQs
Serialize and sanitize JSON data using TypeScript.
We found that scrubbr demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
GitHub removed 27 malicious pull requests attempting to inject harmful code across multiple open source repositories, in another round of low-effort attacks.
Security News
RubyGems.org has added a new "maintainer" role that allows for publishing new versions of gems. This new permission type is aimed at improving security for gem owners and the service overall.
Security News
Node.js will be enforcing stricter semver-major PR policies a month before major releases to enhance stability and ensure reliable release candidates.