Decision card for the open approach question on #21840 and its PR #21877. The withheld security detail stays withheld (RUNNER rule 2): this card names approaches and positions only.
The question
A datasource whose driver ships no config contract (a plugin-contributed driver) has a config that nothing validates. #21840 requires that credential material in that config never sits in metadata in clear text and is never served back.
PR #21877 meets this by guessing from key names and value shapes. A shared walk decides which keys and values look like credentials. The write door refuses what the walk finds, and the read door withholds it. Four rounds of independent security review each found new misses or false positives, and each round grew the rule:
- arrays, header pairs and header lines;
- connection-string forms;
- PEM key material;
- non-ASCII and confusable key names;
- SQL placeholders and prose.
The PR now adds about 4,000 lines, against 1,230 in round 1. The rule file alone is 1,651 lines, and the rule is a public export (isCredentialShapedConfigKey), so every later correction is another accept-set narrowing. No datasource in this repository uses a contractless driver today.
How established systems do it
- Declaration is the boundary.
- Grafana data-source plugins split their config into
jsonData and secureJsonData; the second part is encrypted and never returned to the browser.
- Terraform provider schemas mark attributes
Sensitive.
- Kubernetes keeps credentials in
Secret objects.
- Salesforce has Named Credentials.
- ObjectStack's own known drivers already work this way: their config contracts plus the bound secret (
external.credentialsRef, ADR-0062 D3).
- Key-name matching is a backstop only. Airflow's secrets masker and Sentry's data scrubbing mask keys such as
password, token and api_key in logs and UIs. They are documented as best effort and are not the boundary.
Options
- A — Declaration, and opaque by default (recommended).
- With no config contract, the read door serves the key names but withholds every string value of
config.
- The write door keeps only a small, stable refusal of obvious inline credentials, or none, with the bound secret as the documented route.
- A plugin driver that wants its config shown registers a config contract that marks its secret fields, the same way the shipped drivers do.
- The heuristic walk is removed or reduced to a non-public backstop.
- Cost: an administrator cannot read back the plain settings of a contractless datasource until its driver registers a contract. No datasource in this repository is affected.
- B — Keep the key-name heuristic and continue until review converges. At least one more review round. The rule stays public, so each later fix is another breaking narrowing, and coverage is never complete by construction.
- C — Land round 1 (the small heuristic) now and file the rest as follow-ups. Round 1 has known medium-severity misses.
Recommendation
A. It matches how established systems draw the line. It fails closed by construction instead of by enumeration, and it keeps the public surface small. B and C keep a boundary that depends on guessing.
Related: #21840, #21877, ADR-0015 §10, ADR-0062 D3, ADR-0100.
维护者速读
#21877 现在是靠“字段名像不像密钥”来判断插件驱动 config 里的凭据,复审一轮一轮补,已经到 4000 行,而且永远补不全。主流系统(Grafana、Terraform、Kubernetes、Salesforce)都是让驱动或插件声明哪些字段是密钥;按字段名匹配只用来遮盖日志,作为兜底。
- A(推荐):没有声明的驱动,config 的值读取时一律隐藏,只露出键名;想正常显示,就让插件驱动注册配置约定。代码大幅变小,默认就是安全的。
- B:继续补猜测规则。
- C:先合第一版小规则,剩下的另开卡。
Generated by Claude Code
Decision card for the open approach question on #21840 and its PR #21877. The withheld security detail stays withheld (RUNNER rule 2): this card names approaches and positions only.
The question
A datasource whose driver ships no config contract (a plugin-contributed driver) has a
configthat nothing validates. #21840 requires that credential material in thatconfignever sits in metadata in clear text and is never served back.PR #21877 meets this by guessing from key names and value shapes. A shared walk decides which keys and values look like credentials. The write door refuses what the walk finds, and the read door withholds it. Four rounds of independent security review each found new misses or false positives, and each round grew the rule:
The PR now adds about 4,000 lines, against 1,230 in round 1. The rule file alone is 1,651 lines, and the rule is a public export (
isCredentialShapedConfigKey), so every later correction is another accept-set narrowing. No datasource in this repository uses a contractless driver today.How established systems do it
jsonDataandsecureJsonData; the second part is encrypted and never returned to the browser.Sensitive.Secretobjects.external.credentialsRef, ADR-0062 D3).password,tokenandapi_keyin logs and UIs. They are documented as best effort and are not the boundary.Options
config.Recommendation
A. It matches how established systems draw the line. It fails closed by construction instead of by enumeration, and it keeps the public surface small. B and C keep a boundary that depends on guessing.
Related: #21840, #21877, ADR-0015 §10, ADR-0062 D3, ADR-0100.
维护者速读
#21877 现在是靠“字段名像不像密钥”来判断插件驱动 config 里的凭据,复审一轮一轮补,已经到 4000 行,而且永远补不全。主流系统(Grafana、Terraform、Kubernetes、Salesforce)都是让驱动或插件声明哪些字段是密钥;按字段名匹配只用来遮盖日志,作为兜底。
Generated by Claude Code