// Unless explicitly stated otherwise all files in this repository are licensed
// under the Apache License Version 2.0.
// This product includes software developed at Datadog (https://www.datadoghq.com/).
// Copyright 2026-present Datadog, Inc.

// Exploratory pentest for the wc builtin — GTFOBins validation.
//
// GTFOBins documents wc as capable of reading file contents via
// "wc --files0-from /path/to/file". This flag is intentionally not
// implemented in rshell, so pflag rejects it as an unknown flag.
// See: https://gtfobins.org/gtfobins/wc/

package wc_test

import (
	"os"
	"path/filepath"
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"

	"github.com/DataDog/rshell/interp"
)

// TestWcGTFOBinsFiles0FromRejected verifies that the GTFOBins file-read
// technique "wc --files0-from" is blocked because the flag is not implemented.
//
// GTFOBins: https://gtfobins.org/gtfobins/wc/
// Technique: wc --files0-from /path/to/input-file
func TestWcGTFOBinsFiles0FromRejected(t *testing.T) {
	dir := t.TempDir()
	writeFile(t, dir, "target.txt", "secret data\n")
	_, stderr, code := cmdRun(t, "wc --files0-from target.txt", dir)
	assert.Equal(t, 1, code)
	assert.Contains(t, stderr, "wc:")
}

// TestWcGTFOBinsFileReadSandboxEscape verifies that wc cannot read files
// outside the AllowedPaths sandbox.
//
// GTFOBins: https://gtfobins.org/gtfobins/wc/
// Technique: wc /path/to/input-file (reads file to count lines/words/bytes)
func TestWcGTFOBinsFileReadSandboxEscape(t *testing.T) {
	allowed := t.TempDir()
	secret := t.TempDir()
	require.NoError(t, os.WriteFile(filepath.Join(secret, "secret.txt"), []byte("secret data"), 0644))
	secretPath := filepath.ToSlash(filepath.Join(secret, "secret.txt"))
	_, stderr, code := runScript(t, "wc "+secretPath, allowed, interp.AllowedPaths([]string{allowed}))
	assert.Equal(t, 1, code)
	assert.Contains(t, stderr, "wc:")
}

// TestWcGTFOBinsFileReadTraversal verifies that path traversal cannot
// escape the sandbox when using wc.
//
// GTFOBins: https://gtfobins.org/gtfobins/wc/
// Technique: wc ../../etc/passwd
func TestWcGTFOBinsFileReadTraversal(t *testing.T) {
	dir := t.TempDir()
	_, stderr, code := cmdRun(t, "wc ../../etc/passwd", dir)
	assert.Equal(t, 1, code)
	assert.Contains(t, stderr, "wc:")
}
