mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-15 05:36:17 -08:00
fix(sources): name check hides values under short account keys
The name check used the log redactor's key list, which leaves out the short keys `pass`, `pas`, `user` and `usr` that the URL stripper drops. Both now share `isDisplaySensitiveKey`, so a name holding `?pass=…` collapses to the host; `user`/`usr` are account names like `username` and stay shown at the top level, as by design. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
e4d22cbac8
commit
94faaa3fc4
3 files changed
+27
-4
No files matched your search
@@ -74,6 +74,24 @@ describe('sourceDisplayName', () => {
|
||||
|
||||
it('keeps an account name in the name: it is shown by design', () => {
|
||||
expect(sourceDisplayName({ title: 'joe', url: M3U_URL })).toBe('joe');
|
||||
expect(
|
||||
sourceDisplayName({
|
||||
title: 'joe',
|
||||
url: 'https://host.test/list?usr=joe&pass=hunter2',
|
||||
})
|
||||
).toBe('joe');
|
||||
});
|
||||
|
||||
it('drops a name holding a password under a short account key', () => {
|
||||
for (const key of ['pass', 'pas', 'PASS']) {
|
||||
const url = `https://host.test/list?user=joe&${key}=hunter2`;
|
||||
expect(sourceDisplayName({ title: 'hunter2', url })).toBe(
|
||||
'host.test'
|
||||
);
|
||||
expect(sourceDisplayName({ title: 'Mine hunter2', url })).toBe(
|
||||
'host.test'
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('shows the host for a name an import took from a URL fragment', () => {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { isSensitiveKey } from '@iptvnator/shared/logging';
|
||||
import {
|
||||
PlaylistMeta,
|
||||
playlistDisplayLabel,
|
||||
@@ -6,6 +5,7 @@ import {
|
||||
resolvePlaylistSourceKind,
|
||||
} from '@iptvnator/shared/interfaces';
|
||||
import {
|
||||
isDisplaySensitiveKey,
|
||||
isXtreamAccountPath,
|
||||
stripUrlCredentials,
|
||||
unwrapNestedValue,
|
||||
@@ -26,7 +26,7 @@ export type SourceDisplayFields = Partial<
|
||||
>;
|
||||
|
||||
/** The account name stays on screen by design; every other secret goes. */
|
||||
const SHOWN_ACCOUNT_KEYS = new Set(['username', 'login']);
|
||||
const SHOWN_ACCOUNT_KEYS = new Set(['username', 'login', 'user', 'usr']);
|
||||
/** Shorter values match ordinary words, not secrets. */
|
||||
const MIN_SECRET_LENGTH = 3;
|
||||
const ABSOLUTE_URL = /^[a-z][a-z0-9+.-]*:\/\//i;
|
||||
@@ -110,7 +110,7 @@ function collectUrlSecrets(
|
||||
const visit = (params: URLSearchParams): void =>
|
||||
params.forEach((value, key) => {
|
||||
const normalized = key.toLowerCase().replace(/[^a-z0-9]/g, '');
|
||||
if (isSensitiveKey(key)) {
|
||||
if (isDisplaySensitiveKey(key)) {
|
||||
if (depth > 0 || !SHOWN_ACCOUNT_KEYS.has(normalized)) {
|
||||
secrets.push(value);
|
||||
}
|
||||
|
||||
@@ -70,7 +70,12 @@ export function isXtreamAccountPath(
|
||||
);
|
||||
}
|
||||
|
||||
function isDisplaySensitiveKey(key: string): boolean {
|
||||
/**
|
||||
* A parameter whose value must not be on screen: every key the log redactor
|
||||
* treats as sensitive, plus the short account keys (`pass`, `usr`, …).
|
||||
* The name check uses the same predicate, so it hides what the URL hides.
|
||||
*/
|
||||
export function isDisplaySensitiveKey(key: string): boolean {
|
||||
return SHORT_ACCOUNT_KEYS.has(key.toLowerCase()) || isSensitiveKey(key);
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user