Skip to content

security(eval): clés computed fail-closed + flux de valeur (SB-RCE-2026-01) - #506

Merged
simonLouvet merged 1 commit into
masterfrom
security/validator-fail-closed
Sep 9, 2026
Merged

simonLouvet merged 1 commit into
masterfrom
security/validator-fail-closed

Conversation

@simonLouvet

Copy link
Copy Markdown
Collaborator

Review chercheur 2026-08-26 — clés computed statiquement constantes

Nouvelle review de Maxim Yakovlev : foldStaticValue ne résolvait que 3 types de nœuds ; tout nœud statiquement constant d'un autre type était traité comme dynamique et contournait les gardes.

Vérifié (reproduit avant correctif)

  • he[(0,'constructor')][(0,'constructor')]('return process.pid')()accepté + exécute (retourne process.pid).
  • _[(0,'template')]('<%= 7*6 %>')({})accepté + exécute (reopen lodash.template → '42').

Correctif — posture fail-closed + flux de valeur

  • KNOWN_BINDINGS (libs + globals + new whitelist) : clé sans variable libre = statiquement constante.
  • foldStaticValue étendu (séquence, logique, ternaire, unaire, index/membre de littéraux).
  • resolveKey : constante → repliée+contrôlée ; constante non résolvable → rejetée ; clé à variable libre → acceptée (résiduel) mais tout sous-chemin atteignant une valeur interdite → rejeté.

Vérifié après correctif

  • 21 cas du chercheur bloqués (dont les 2 PoC end-to-end).
  • 28 patterns prod OK, 182 tests engine, lint 0 erreur.

…2026-01, review 2026-08-26)

Nouvelle review du chercheur : foldStaticValue ne résolvait que 3 types de
nœuds (Literal, TemplateLiteral statique, '+') ; tout autre nœud statiquement
constant était traité comme dynamique et contournait les gardes
FORBIDDEN_PROPERTIES / whitelist. Formes acceptées à tort :
  he[(0,'constructor')]  (séquence)
  he[(false||'constructor')]  (logique)
  he[(1?'constructor':'x')]  (ternaire)
  he[['constructor'][0]]  (index de tableau)
  he[String.fromCharCode(99,111,...)]  (appel)
  _[(0,'template')]('<%= 7*6 %>')({})  (reopen lodash.template)

Correctif (posture fail-closed + flux de valeur) :
- KNOWN_BINDINGS (libs + globals autorisés + new whitelist) : une clé sans
  variable libre est statiquement constante ;
- foldStaticValue étendu (séquence, logique ||/&&/??, ternaire, unaire,
  index/membre de littéraux, tableaux/objets littéraux) ;
- resolveKey : constante → repliée et contrôlée ; constante non résolvable
  (appel, méthode de littéral, ...) → REJETÉE (fail-closed) ; clé à variable
  libre → acceptée (résiduel) MAIS tout sous-chemin atteignant une valeur
  interdite → rejeté ((x?['constructor']:[v])[0], (obj,'constructor')).
- Vérifié : 21 cas du chercheur bloqués, 28 patterns prod OK, 182 tests engine.
@simonLouvet
simonLouvet merged commit 7033309 into master Sep 9, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant