JavaScript Import Attributes and Assertions Guide
JavaScript Import Attributes, originally introduced as Import
Assertions, are a syntax feature in ECMAScript modules that allow
developers to provide explicit metadata alongside module specifiers.
This article covers what Import Attributes and Assertions are, why they
were introduced to resolve security and MIME-type vulnerabilities, how
the syntax evolved from assert to with, and
practical code examples for both static and dynamic imports.
The Purpose of Import Attributes
Traditionally, JavaScript module loaders rely entirely on the MIME
type sent by the server to determine how to execute a file. This creates
a security risk known as a MIME-type confusion attack. For example, if a
developer intends to import a static JSON configuration file, but a
server accidentally or maliciously returns an executable JavaScript file
with a text/javascript MIME type, the browser would execute
the script in the current origin.
Import Attributes solve this issue by allowing the importing module to declare the expected resource type explicitly. If the fetched resource does not match the specified type, the module loading fails before any code executes.
Transition from
assert to with
The proposal initially introduced the assert keyword
(Import Assertions). However, TC39 (the JavaScript standards committee)
updated the specification to use the with keyword (Import
Attributes).
The change occurred because “assertions” were strictly meant to be non-functional checks that could not alter how a module is interpreted or fetched. To support broader use cases—such as specifying alternative module evaluation formats, CSS modules, or WebAssembly modules—the syntax transitioned to “attributes,” which can influence module resolution and interpretation.
Static Import Syntax
Static imports use the with clause after the module
specifier to indicate the module type.
// Modern standard (Import Attributes)
import config from './config.json' with { type: 'json' };
// Deprecated syntax (Import Assertions)
// import config from './config.json' assert { type: 'json' };In environments that support CSS modules, you can apply the same syntax to import stylesheets:
import sheet from './styles.css' with { type: 'css' };Dynamic Import Syntax
Dynamic imports (import()) accept an options object as a
second argument containing the with property:
async function loadConfig() {
const module = await import('./config.json', {
with: { type: 'json' }
});
console.log(module.default);
}Key Benefits
- Security: Prevents unexpected script execution from untrusted or misconfigured servers when loading non-code assets.
- Clarity: Makes module dependencies explicit in the codebase, signaling exact file requirements to tools, bundlers, and runtime engines.
- Extensibility: Provides a standard path for browsers and runtimes (like Node.js and Deno) to support new resource types, such as CSS, JSON, and WebAssembly, natively within the ES module ecosystem.