( app: App, choice: IChoice, )
| 140 | } |
| 141 | |
| 142 | async function buildSecretOptionNamesByPath( |
| 143 | app: App, |
| 144 | choice: IChoice, |
| 145 | ): Promise<Map<string, ReadonlySet<string> | null>> { |
| 146 | const paths = new Set<string>(); |
| 147 | collectUserScriptPathsFromChoice(choice, paths); |
| 148 | const secretOptionNamesByPath = new Map<string, ReadonlySet<string> | null>(); |
| 149 | |
| 150 | for (const path of paths) { |
| 151 | try { |
| 152 | // A Macro choice's userscript path comes from data.json, which is untrusted |
| 153 | // on a synced/shared/imported vault. Never stat or read an out-of-vault path |
| 154 | // (e.g. "../../../etc/passwd"); treat it as not-present, mirroring the package |
| 155 | // import probes (escapesVaultBoundary, #1434). |
| 156 | if (escapesVaultBoundary(path)) continue; |
| 157 | |
| 158 | const exists = await app.vault.adapter.exists(path); |
| 159 | if (!exists) continue; |
| 160 | |
| 161 | const detection = detectUserScriptSecretOptions( |
| 162 | await app.vault.adapter.read(path), |
| 163 | path, |
| 164 | ); |
| 165 | secretOptionNamesByPath.set( |
| 166 | path, |
| 167 | detection.foundSecretOptions && detection.names.size === 0 |
| 168 | ? null |
| 169 | : detection.names, |
| 170 | ); |
| 171 | } catch (error) { |
| 172 | log.logWarning( |
| 173 | `QuickAdd could not inspect user-script settings '${path}' while duplicating choice: ${ |
| 174 | (error as Error)?.message ?? error |
| 175 | }`, |
| 176 | ); |
| 177 | } |
| 178 | } |
| 179 | |
| 180 | return secretOptionNamesByPath; |
| 181 | } |
| 182 | |
| 183 | /** |
| 184 | * Get the appropriate builder for a choice |
no test coverage detected