-
Notifications
You must be signed in to change notification settings - Fork 0
Security by Design
CCM follows a security-by-design approach that is rooted in strict encapsulation, explicit references, and controlled resource loading.
Component instances are created and accessed exclusively via explicit JavaScript references returned by ccm.start() or ccm.instance(). There is no global registry of running instances and no implicit access via the DOM or global variables. As a result, externally loaded JavaScript code cannot discover or interact with component instances unless it has been given an explicit reference.
const instance = await ccm.instance("./ccm.quiz.mjs", {
questions: [ /* ... */ ]
}, document.body);
// Only this reference can access the instance
await instance.start();
// ❌ Not possible:
window.findInstance(instance); // cannot be find
document.querySelector(...); // no access to instance logicExternally loaded or compromised scripts cannot “discover” or hijack running instances.
Component definitions are encapsulated by the framework. When a component is registered, the original definition is stored privately inside the ccmjs framework and is never exposed globally. Calls to ccm.component() return only a cloned copy of the registered component object. This ensures that once a component version is registered, it cannot be modified accidentally or intentionally by other scripts.
let comp = await ccm.component("./ccm.hello.mjs");
// This modifies only the cloned copy
comp.config.hacked = true;
// The internally registered component version remains unchanged
// Re-registering a component with the same name and version does not override the
// original definition, but only returns a clone of the already registered component.
comp = await ccm.component({
name: "hello",
hacked: true,
// ...
});
console.log(comp.hacked); // undefinedOnce a component is registered, it is protected from accidental or malicious mutation by externally loaded JavaScript.
CCM supports Subresource Integrity when loading components or resources, ensuring that only resources matching a known cryptographic hash are executed.
ccm.start(
"./ccm.quiz.mjs#sha384-...", // component loaded with SRI
{
ccm: "./ccm.js#sha384-...", // used ccmjs version loaded with SRI
css: [ "ccm.load", {
url: "styles.css",
attr: {
integrity: "sha384-...", // CSS loaded with SRI
crossorigin: "anonymous"
}
}],
js: [ "ccm.load", {
url: "script.js",
attr: {
integrity: "sha384-...", // JS loaded with SRI
crossorigin: "anonymous"
}
}],
module: [ "ccm.load", {
url: "./module.mjs",
attr: {
integrity: "sha384-...", // Module loaded with SRI
crossorigin: "anonymous"
}
}]
}
);Even if a CDN or server is compromised, manipulated resources are rejected by the browser because the integrity hash no longer matches.
Each component instance is rendered inside a Shadow DOM by default, with configurable control over its openness.
The root configuration option supports the following values:
-
"open"(default): a Shadow DOM is created and accessible viainstance.root -
"closed": a Shadow DOM is created but not externally accessible -
"none": no Shadow DOM is used; the component renders directly into the host element
ccm.start("./ccm.hello.mjs", {
root: "closed"
}, document.body);When enabled, the Shadow DOM encapsulates DOM structure, styles, and internal markup from external scripts, reducing accidental interference and improving isolation.