diff --git a/dogen/plugins/cct.py b/dogen/plugins/cct.py
index b4ada30..3b3ab63 100644
--- a/dogen/plugins/cct.py
+++ b/dogen/plugins/cct.py
@@ -19,7 +19,7 @@ class CCT(Plugin):
         Read in a schema definition for our part of the config and hook it
         into the parent schema at the cct: top-level key.
         """
-        schema_path = os.path.join(self.dogen.pwd, "plugins", "cct", "cct_schema.yaml")
+        schema_path = os.path.join(self.dogen.pwd, "schema", "cct_schema.yaml")
         schema = {}
         with open(schema_path, 'r') as fh:
             schema = yaml.safe_load(fh)
@@ -50,6 +50,9 @@ class CCT(Plugin):
         if 'runtime' in cfg['cct']:
             self.runtime_changes(cfg)
 
+        if not 'user' in cfg['cct']:
+            cfg['cct']['user'] = 'root'
+
     def _prepare_modules(self, cfg):
         for module in cfg['cct']['modules']:
             name = None
diff --git a/dogen/plugins/cct/__init__.py b/dogen/plugins/cct/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/dogen/plugins/cct/cct_schema.yaml b/dogen/schema/cct_schema.yaml
similarity index 96%
rename from dogen/plugins/cct/cct_schema.yaml
rename to dogen/schema/cct_schema.yaml
index 1cf2751..0b32caf 100644
--- a/dogen/plugins/cct/cct_schema.yaml
+++ b/dogen/schema/cct_schema.yaml
@@ -15,3 +15,4 @@ map:
   runtime_changes: { type: str }
   # same rationale as for configure
   runtime: { type: any }
+  user: { type: any }
diff --git a/dogen/templates/template.jinja b/dogen/templates/template.jinja
index eac14d4..b0a6b41 100644
--- a/dogen/templates/template.jinja
+++ b/dogen/templates/template.jinja
@@ -102,6 +102,7 @@ RUN [ "bash", "-x", "/tmp/scripts/{{ script.package }}/{{ script.exec }}" ]
 {% if cct %}
 ADD cct /tmp/cct/
 ENV CCT_MODULES_PATH=/tmp/cct/
+USER {{ cct.user }}
 RUN cct {%if cct.verbose %}-v{% endif %} {% for run in cct.run %} /tmp/cct/{{ run }} {% endfor %}
 
 # Add cct in command mode as entrypoint

build-time cct user depends on whether or not scripts run
since we don't explicitly define a USER for the cct block, it uses whatever was last set. That depends on what scripts are run and under what uid.

We should probably default to USER root in the cct block and perhaps let it be overridden in the YAML.
diff --git a/tests/test_cct_plugin.py b/tests/test_cct_plugin.py
new file mode 100644
index 0000000..1cc4c24
--- /dev/null
+++ b/tests/test_cct_plugin.py
@@ -0,0 +1,26 @@
+import tempfile
+import unittest
+import shutil
+
+from dogen.plugins import cct
+
+# minimal fake dogen object
+class MockDogen():
+    def __init__(self):
+        self.log = 0
+        self.descriptor = 0
+        self.output = ""
+
+class TestCCTPlugin(unittest.TestCase):
+    def setUp(self):
+        self.workdir = tempfile.mkdtemp(prefix='test_cct_plugin')
+        self.cct = cct.CCT(dogen=MockDogen())
+
+    def teardown(self):
+        shutil.rmtree(self.workdir)
+
+    def test_default_user_root(self):
+        cfg = { 'cct': { 'configure': '' }}
+        self.cct.prepare(cfg)
+        self.assertTrue('user' in cfg['cct'])
+        self.assertEqual(cfg['cct']['user'], "root")

pip install -e .[dev]
parse_log_pytest
requirements.txt
pytest pytest-cov mock
apt-get update apt-get install -y gcc
3.9
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
coverage==7.8.0
docopt==0.6.2
-e git+https://github.com/jboss-dockerfiles/dogen.git@26146b1b97b780e2f280fadb4cc85336307a2ea6#egg=dogen
exceptiongroup==1.2.2
iniconfig==2.1.0
Jinja2==2.8
MarkupSafe==3.0.2
mock==5.2.0
packaging==24.2
pluggy==1.5.0
pykwalify==1.8.0
pytest==8.3.5
pytest-cov==6.0.0
python-dateutil==2.9.0.post0
PyYAML==3.11
requests==2.8.1
ruamel.yaml==0.18.10
ruamel.yaml.clib==0.2.12
six==1.10.0
tomli==2.2.1

name: dogen
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=3.0.16=h5eee18b_0
  - pip=25.0=py39h06a4308_0
  - python=3.9.21=he870216_1
  - readline=8.2=h5eee18b_0
  - setuptools=75.8.0=py39h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tzdata=2025a=h04d1e81_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - coverage==7.8.0
      - docopt==0.6.2
      - exceptiongroup==1.2.2
      - iniconfig==2.1.0
      - jinja2==2.8
      - markupsafe==3.0.2
      - mock==5.2.0
      - packaging==24.2
      - pluggy==1.5.0
      - pykwalify==1.8.0
      - pytest==8.3.5
      - pytest-cov==6.0.0
      - python-dateutil==2.9.0.post0
      - pyyaml==3.11
      - requests==2.8.1
      - ruamel-yaml==0.18.10
      - ruamel-yaml-clib==0.2.12
      - six==1.10.0
      - tomli==2.2.1
prefix: /opt/conda/envs/dogen

tests/test_cct_plugin.py::TestCCTPlugin::test_default_user_root
dogen/plugins/cct.py dogen/plugins/cct/__init__.py dogen/templates/template.jinja dogen/plugins/cct/cct_schema.yaml
dogen/plugins/cct.py dogen/plugins/cct/__init__.py dogen/schema/cct_schema.yaml dogen/templates/template.jinja