Skip to content

Commit e1e56a8

Browse files
authored
Merge pull request #8722 from achouhan09/account-space-fix
NC | CLI | Added a validation to check if whitespace is not trimmed from string value for a flag
2 parents 1bbd42e + b60a15f commit e1e56a8

File tree

2 files changed

+110
-0
lines changed

2 files changed

+110
-0
lines changed

src/manage_nsfs/manage_nsfs_validations.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ const notifications_util = require('../util/notifications_util');
2929
* @param {object} argv
3030
*/
3131
async function validate_input_types(type, action, argv) {
32+
validate_no_extra_args(argv._);
3233
validate_type_and_action(type, action);
3334
// when we use validate_no_extra_options we don't care about the value, only the flags
3435
const input_options = Object.keys(argv);
@@ -85,6 +86,35 @@ function validate_type_and_action(type, action) {
8586
}
8687
}
8788

89+
/**
90+
* validate_no_extra_args ensures that the parsed arguments contain only the expected type and action
91+
* if `argv_` contains more than two elements (type and action), it indicate extra argument which may be due to:
92+
* - Leading spaces in flag values (e.g., `--new_buckets_path= abc/`)
93+
* - Additional unexpected arguments passed from the command line
94+
*
95+
* ### CLI Parsing Behavior:
96+
* When passing arguments via CLI, if a flag's value starts with a space or consists only of whitespace,
97+
* the shell may treat it differently:
98+
* - Leading spaces - might be preserved when quoted (`--new_buckets_path=" abc/"`).
99+
* - Unquoted values with spaces - may cause incorrect parsing (`--new_buckets_path= abc/` is interpreted as an empty value).
100+
* - The parsed argument structure typically follows:
101+
* ```json
102+
* { _: [ "command", "action" ], flag1: "value1", flag2: "value2", ... }
103+
* ```
104+
* - The `_` array should contain only the command and action. If additional elements appear,
105+
* it suggests an issue with flag values (e.g., an incorrectly formatted or empty value).
106+
*
107+
* @param {string[]} argv_
108+
* @throws {ManageCLIError}
109+
*/
110+
function validate_no_extra_args(argv_) {
111+
// checking if 'argv_' contains more then 2 values (i.e, type and action)
112+
if (argv_.length > 2) {
113+
const details = `unexpected extra arguments detected: ${JSON.stringify(argv_.slice(2))}, ensure flag values are correctly formatted.`;
114+
throw_cli_error(ManageCLIError.InvalidArgument, details);
115+
}
116+
}
117+
88118
/**
89119
* validate_identifier will validate that we have the needed identifier for the command
90120
* @param {string} type
@@ -718,3 +748,4 @@ exports.validate_whitelist_arg = validate_whitelist_arg;
718748
exports.validate_whitelist_ips = validate_whitelist_ips;
719749
exports.validate_flags_combination = validate_flags_combination;
720750
exports.validate_connection_args = validate_connection_args;
751+
exports.validate_no_extra_args = validate_no_extra_args;

src/test/unit_tests/jest_tests/test_nc_account_cli.test.js

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ const timeout = 50000;
2323
const config = require('../../../../config');
2424
const config_fs_account_options = { show_secrets: true, decrypt_secret_key: true };
2525

26+
const quoted_type = Object.freeze({
27+
SPACE_ONLY: "s", // space only
28+
QUOTE_SPACE: "qs", // quote then space
29+
SPACE_QUOTE: "sq", // space then quote
30+
});
31+
2632
// eslint-disable-next-line max-lines-per-function
2733
describe('manage nsfs cli account flow', () => {
2834
describe('cli create account', () => {
@@ -103,6 +109,33 @@ describe('manage nsfs cli account flow', () => {
103109
assert_account(account_symlink, account_options);
104110
});
105111

112+
it('should fail - cli create account invalid new_buckets_path (leading space in new_buckets_path)', async () => {
113+
const { type, name, uid, gid, new_buckets_path } = defaults;
114+
const account_options = { config_root, name, uid, gid}; // will add new_buckets_path with leading space later
115+
const action = ACTIONS.ADD;
116+
const command = create_command(type, action, account_options);
117+
const res = await exec_manage_cli_add_leading_space_option(command, 'new_buckets_path', new_buckets_path, quoted_type.SPACE_ONLY);
118+
expect(JSON.parse(res.stdout).error.code).toBe(ManageCLIError.InvalidArgument.code);
119+
});
120+
121+
it('should fail - cli create account invalid new_buckets_path (leading space in quoted new_buckets_path)', async () => {
122+
const { type, name, uid, gid, new_buckets_path } = defaults;
123+
const account_options = { config_root, name, uid, gid}; // will add quoted new_buckets_path with leading space later
124+
const action = ACTIONS.ADD;
125+
const command = create_command(type, action, account_options);
126+
const res = await exec_manage_cli_add_leading_space_option(command, 'new_buckets_path', new_buckets_path, quoted_type.SPACE_QUOTE);
127+
expect(JSON.parse(res.stdout).error.code).toBe(ManageCLIError.InvalidArgument.code);
128+
});
129+
130+
it('should fail - cli create account invalid new_buckets_path (quoted leading space in new_buckets_path)', async () => {
131+
const { type, name, uid, gid, new_buckets_path } = defaults;
132+
const account_options = { config_root, name, uid, gid}; // will add new_buckets_path with quoted leading space later
133+
const action = ACTIONS.ADD;
134+
const command = create_command(type, action, account_options);
135+
const res = await exec_manage_cli_add_leading_space_option(command, 'new_buckets_path', new_buckets_path, quoted_type.QUOTE_SPACE);
136+
expect(JSON.parse(res.stdout).error.code).toBe(ManageCLIError.InvalidAccountNewBucketsPath.code); // should get this error if space is also quoted with the value
137+
});
138+
106139
it('should fail - cli update account invalid access_key - invalid size', async () => {
107140
const { type, secret_key, name, new_buckets_path, uid, gid } = defaults;
108141
const account_options = { config_root, access_key: 'abc', secret_key, name, new_buckets_path, uid, gid };
@@ -2218,6 +2251,52 @@ async function exec_manage_cli_add_empty_option(command, option) {
22182251
return res;
22192252
}
22202253

2254+
/**
2255+
* exec_manage_cli_add_leading_space_option modifies the command by appending a flag with a value(quoted or non-quoted) that includes a leading space to test CLI parsing behavior
2256+
* @param {string} command
2257+
* @param {string} option
2258+
* @param {string} value
2259+
* @param {"s" | "qs" | "sq" | "default"} quoted
2260+
*
2261+
* @examples
2262+
* - await exec_manage_cli_add_leading_space_option("cli_command", "flag", "val", quoted_type.SPACE_ONLY);
2263+
* // cli_command --flag= val (Space before value)
2264+
*
2265+
* - await exec_manage_cli_add_leading_space_option("cli_command", "flag", "val", quoted_type.QUOTE_SPACE);
2266+
* // cli_command --flag=" val" (quote then space)
2267+
*
2268+
* - await exec_manage_cli_add_leading_space_option("cli_command", "flag", "val", quoted_type.SPACE_QUOTE);
2269+
* // cli_command --flag= "val" (space then quote)
2270+
*
2271+
* - await exec_manage_cli_add_leading_space_option("cli_command", "flag", "val");
2272+
* // cli_command --flag=val (No special formatting)
2273+
*/
2274+
async function exec_manage_cli_add_leading_space_option(command, option, value, quoted = "default") {
2275+
let changed_command;
2276+
2277+
switch (quoted) {
2278+
case quoted_type.SPACE_ONLY:
2279+
changed_command = `${command} --${option}= ${value}`;
2280+
break;
2281+
case quoted_type.QUOTE_SPACE:
2282+
changed_command = `${command} --${option}=" ${value}"`;
2283+
break;
2284+
case quoted_type.SPACE_QUOTE:
2285+
changed_command = `${command} --${option}= "${value}"`;
2286+
break;
2287+
default:
2288+
changed_command = `${command} --${option}=${value}`;
2289+
}
2290+
2291+
let res;
2292+
try {
2293+
res = await os_util.exec(changed_command, { return_stdout: true });
2294+
} catch (e) {
2295+
res = e;
2296+
}
2297+
return res;
2298+
}
2299+
22212300
/**
22222301
* create_command would create the string needed to run the CLI command
22232302
* @param {string} type

0 commit comments

Comments
 (0)