Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/four-garlics-attack.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@nodesecure/js-x-ray": minor
---

Implement i18n translation locally for warnings
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,8 @@ Warnings support internationalization through the `@nodesecure/i18n` package. Ea
import * as jsxray from "@nodesecure/js-x-ray";
import * as i18n from "@nodesecure/i18n";

await i18n.extendFromSystemPath(jsxray.i18nLocation());

const message = i18n.getTokenSync(
jsxray.warnings["parsing-error"].i18n
);
Expand Down
1 change: 1 addition & 0 deletions workspaces/js-x-ray/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
"ts-pattern": "^5.0.6"
},
"devDependencies": {
"@nodesecure/i18n": "4.0.3",
"astring": "1.9.0",
"mitata": "1.0.34"
}
Expand Down
27 changes: 27 additions & 0 deletions workspaces/js-x-ray/src/i18n/english.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
const sast_warnings = {
parsing_error: "An error occured when parsing the JavaScript code with meriyah. It mean that the conversion from string to AST has failed. If you encounter such an error, please open an issue here.",
unsafe_import: "Unable to follow an import (require, require.resolve) statement/expr.",
unsafe_regex: "A RegEx as been detected as unsafe and may be used for a ReDoS Attack.",
unsafe_stmt: "Usage of dangerous statement like eval() or Function(\"\").",
unsafe_assign: "Assignment of a protected global like process or require.",
encoded_literal: "An encoded literal has been detected (it can be an hexa value, unicode sequence, base64 string etc)",
suspicious_file: "A suspicious file with more than ten encoded-literal in it.",
short_identifiers: "This mean that all identifiers has an average length below 1.5. Only possible if the file contains more than 5 identifiers.",
suspicious_literal: "This mean that the sum of suspicious score of all Literals is bigger than 3.",
obfuscated_code: "There's a very high probability that the code is obfuscated...",
weak_crypto: "The code probably contains a weak crypto algorithm (md5, sha1...)",
shady_link: "A Literal (string) contains an URL to a domain with a suspicious extension.",
zero_semver: "Semantic version starting with 0.x (unstable project or without serious versioning)",
empty_package: "The package tarball only contains a package.json file.",
unsafe_command: "Usage of suspicious child_process command such as spawn() or exec()",
serialize_environment: "The code attempts to serialize process.env which could lead to environment variable exfiltration",
synchronous_io: "The code contains synchronous I/O operations, which can block the event loop and degrade performance.",
data_exfiltration: "Detects serialization of sensitive system information (os.userInfo, os.networkInterfaces, os.cpus, dns.getServers) which could indicate unauthorized data collection for external transmission.",
log_usage: "Usage of console logging methods (log, info, warn, error, debug) that may expose sensitive information in production environments.",
sql_injection: "Template literals with interpolated expressions in SQL queries (SELECT, INSERT, UPDATE, DELETE) without proper parameterization, creating potential SQL injection vulnerabilities.",
monkey_patch: "Modification of native prototypes or global objects at runtime, which introduces security risks including flow hijacking, global side effects, and potential concealment of malicious activities."
};

export default {
sast_warnings
}
29 changes: 29 additions & 0 deletions workspaces/js-x-ray/src/i18n/french.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
const sast_warnings = {
parsing_error: `Une erreur s'est produite lors de l'analyse du code JavaScript avec meriyah.
Cela signifie que la conversion de la chaîne de caractères AST a échoué.
Si vous rencontrez une telle erreur, veuillez ouvrir une issue.`,
unsafe_import: "Impossible de suivre l'import (require, require.resolve) statement/expr.",
unsafe_regex: "Un RegEx a été détecté comme non sûr et peut être utilisé pour une attaque ReDoS.",
unsafe_stmt: "Utilisation d'instructions dangereuses comme eval() ou Function(\"\").",
unsafe_assign: "Attribution d'un processus ou d'un require global protégé..",
encoded_literal: "Un code littérale a été découvert (il peut s'agir d'une valeur hexa, d'une séquence unicode, d'une chaîne de caractères base64, etc.)",
short_identifiers: "Cela signifie que tous les identifiants ont une longueur moyenne inférieure à 1,5. Seulement possible si le fichier contient plus de 5 identifiants.",
suspicious_literal: "Cela signifie que la somme des scores suspects de tous les littéraux est supérieure à 3.",
suspicious_file: "Un fichier suspect contenant plus de dix chaines de caractères encodés",
obfuscated_code: "Il y a une très forte probabilité que le code soit obscurci...",
weak_crypto: "Le code contient probablement un algorithme de chiffrement faiblement sécurisé (md5, sha1...).",
shady_link: "Un Literal (string) contient une URL vers un domaine avec une extension suspecte.",
zero_semver: "Version sémantique commençant par 0.x (projet instable ou sans versionnement sérieux)",
empty_package: "L'archive du package ne contient qu'un fichier package.json.",
unsafe_command: "Utilisation d'une commande child_process suspecte, comme spawn() ou exec()",
serialize_environment: "Le code tente de sérialiser process.env, ce qui pourrait entraîner une exfiltration des variables d'environnement",
synchronous_io: "Le code contient des opérations I/O synchrones, ce qui peut bloquer l'event-loop et dégrader les performances.",
data_exfiltration: "Détecte la sérialisation d'informations système sensibles (os.userInfo, os.networkInterfaces, os.cpus, dns.getServers) qui pourrait indiquer une collecte de données non autorisée pour transmission externe.",
log_usage: "Utilisation de méthodes de l'API console (log, info, warn, error, debug) qui peuvent exposer des informations sensibles en environnement de production.",
sql_injection: "Littéraux de gabarit avec expressions interpolées dans les requêtes SQL (SELECT, INSERT, UPDATE, DELETE) sans paramétrisation appropriée, créant des vulnérabilités potentielles d'injection SQL.",
monkey_patch: "Modification des prototypes natifs ou objets globaux à l'exécution, ce qui introduit des risques de sécurité incluant le détournement de flux, des effets secondaires globaux et la dissimulation potentielle d'activités malveillantes."
};

export default {
sast_warnings
}
6 changes: 6 additions & 0 deletions workspaces/js-x-ray/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// Import Node.js Dependencies
import path from "node:path";

export * from "./AstAnalyser.ts";
export * from "./EntryFilesAnalyser.ts";
export * from "./JsSourceParser.ts";
Expand All @@ -10,3 +13,6 @@ export * from "./warnings.ts";
export * from "./CollectableSet.ts";
export * from "./contants.ts";

export function i18nLocation() {
return path.join(import.meta.dirname, "i18n");
}
49 changes: 49 additions & 0 deletions workspaces/js-x-ray/test/Internationalization.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Import Node.js Dependencies
import { describe, it, before, after } from "node:test";
import assert from "node:assert";

// Import Third-party Dependencies
import * as i18n from "@nodesecure/i18n";

// Import Internal Dependencies
import { i18nLocation } from "../src/index.ts";

describe("Internationalization", () => {
let originalLang: string;

before(async() => {
originalLang = await i18n.getLocalLang();
});

after(async() => {
await i18n.setLocalLang(originalLang);
await i18n.getLocalLang();
});

it("should have i18n location defined", () => {
const location = i18nLocation();
assert(typeof location === "string" && location.length > 0, "i18n location should be a non-empty string");
});

it("should have English translations", async() => {
await i18n.extendFromSystemPath(i18nLocation());
await i18n.setLocalLang("english");
await i18n.getLocalLang();

const value = i18n.getTokenSync("sast_warnings.parsing_error");

assert(value !== undefined, "English translations should be defined");
assert(typeof value === "string", "English translation for 'sast_warnings.parsing_error' should be a string");
});

it("should have French translations", async() => {
await i18n.extendFromSystemPath(i18nLocation());
await i18n.setLocalLang("french");
await i18n.getLocalLang();

const value = i18n.getTokenSync("sast_warnings.parsing_error");

assert(value !== undefined, "French translations should be defined");
assert(typeof value === "string", "French translation for 'sast_warnings.parsing_error' should be a string");
});
});