Harden JavaScript SDK
2 minute read
This guide walks you through the steps of setting up and configuring a hardened version of your JavaScript SDK. These steps focus on minimizing the SDK’s reliance on external resources that could be used as an attack surface to disrupt events flow or compromise the app, thereby enhancing security.
SDK hardening steps
- Use a named export that bundles plugins while packaging RudderStack directly in your project using NPM. By using the NPM package export that bundles the plugins code, the SDK does not make any request to dynamically download the plugins.
You can also:
- Self-host the plugin files and integration SDKs and serve them over your domain.
- Proxy the RudderStack domains and use your own domain to serve the JavaScript SDK.
import { RudderAnalytics } from '@rudderstack/analytics-js/bundled';var RudderAnalytics = require("@rudderstack/analytics-js/bundled");- Override/mock source configuration data. By mocking the source configuration response to the SDK, RudderStack does not make any source configuration request again.
rudderAnalytics.load(WRITE_KEY, DATA_PLANE_URL, {
polyfillIfRequired: false,
getSourceConfig: () => ({
updatedAt: new Date().toISOString(),
source: {
// Use relevant valid values from the RudderStack dashboard
name: SOURCE_NAME,
id: SOURCE_ID,
workspaceId: WORKSPACE_ID,
writeKey: WRITE_KEY,
updatedAt: new Date().toISOString(),
config: {
statsCollection: {
errors: {
enabled: false
},
metrics: {
enabled: false
}
}
},
enabled: true,
destinations: []
}
})
});- Disable the loading of polyfills by setting
polyfillIfRequiredtofalse. By disabling polyfills, the SDK does not dynamically add a polyfills script from a third-party domain.
rudderAnalytics.load(WRITE_KEY, DATA_PLANE_URL, {
polyfillIfRequired: false
});RudderStack also recommends using only the cloud mode destinations to avoid loading any other third-party SDKs on the website.
Final instrumentation
import { RudderAnalytics } from '@rudderstack/analytics-js/bundled';
const rudderAnalytics = new RudderAnalytics();
rudderAnalytics.load(WRITE_KEY, DATA_PLANE_URL, {
polyfillIfRequired: false,
getSourceConfig: () => ({
updatedAt: new Date().toISOString(),
source: {
// Use relevant valid values from the RudderStack dashboard
name: SOURCE_NAME,
id: SOURCE_ID,
workspaceId: WORKSPACE_ID,
writeKey: WRITE_KEY,
updatedAt: new Date().toISOString(),
config: {
statsCollection: {
errors: {
enabled: false
},
metrics: {
enabled: false
}
}
},
enabled: true,
destinations: []
}
})
});
export { rudderAnalytics };var RudderAnalytics = require("@rudderstack/analytics-js/bundled");
const rudderAnalytics = new RudderAnalytics();
rudderAnalytics.load(WRITE_KEY, DATA_PLANE_URL, {
polyfillIfRequired: false,
getSourceConfig: () => ({
updatedAt: new Date().toISOString(),
source: {
// Use relevant valid values from the RudderStack dashboard
name: SOURCE_NAME,
id: SOURCE_ID,
workspaceId: WORKSPACE_ID,
writeKey: WRITE_KEY,
updatedAt: new Date().toISOString(),
config: {
statsCollection: {
errors: {
enabled: false
},
metrics: {
enabled: false
}
}
},
enabled: true,
destinations: []
}
})
});
exports.rudderAnalytics = rudderAnalytics;