Page MenuHomePhabricator

generate_user_files creates user-config.py with mode 777 on WSL, and then pywikibot refuse to load the config for security
Open, MediumPublic

Description

Any script being run through pwb.py gives

File "pwb.py", line 257, in <module>
    if not main():
  File "pwb.py", line 250, in main
    run_python_file(filename, [filename] + args, argvu, file_package)
  File "pwb.py", line 119, in run_python_file
    main_mod.__dict__)
  File "./scripts/login.py", line 198, in <module>
    main()
  File "./scripts/login.py", line 180, in main
    site.login(sysop, autocreate=autocreate)
  File "/mnt/c/Users/wesalius/Desktop/core/pywikibot/pywikibot/site.py", line 2103, in login
    site=self, sysop=sysop, user=self._username[sysop])
  File "/mnt/c/Users/wesalius/Desktop/core/pywikibot/pywikibot/tools/__init__.py", line 1737, in wrapper
    return obj(*__args, **__kw)
  File "/mnt/c/Users/wesalius/Desktop/core/pywikibot/pywikibot/login.py", line 120, in __init__
    'wiki_code': self.site.code})
pywikibot.exceptions.NoUsername:  ERROR: Username for test:test is undefined.
If you have an account for that site, please add a line to user-config.py:

usernames['test']['test'] = 'myUsername'
CRITICAL: Exiting due to uncaught exception <class 'pywikibot.exceptions.NoUsername'>

Setup:

Win10 through WSL debian

Pywikibot: [https] wikimedia-pywikibot.git (8d70cc4, g10542, 2018/12/27, 11:00:35, OUTDATED)
Release version: 3.1.dev0
requests version: 2.21.0
  cacerts: /home/wesalius/.local/lib/python3.5/site-packages/certifi/cacert.pem
    certificate test: ok
Python: 3.5.3 (default, Sep 27 2018, 17:25:39)
[GCC 6.3.0 20170516]

User-config.py is read-write for all users, script-generated without any additions to it:

# before the definition of the ‘family’ variable.
family = 'wikipedia'

# The language code of the site we're working on.
mylang = 'cs'

# The dictionary usernames should contain a username for each site where you
# have a bot account. If you have a unique username for all languages of a
# family , you can use '*'
usernames['wikipedia']['cs'] = u'Wesalius'

Event Timeline

Can you provide full content of user-config.py please?

# -*- coding: utf-8 -*-
from __future__ import absolute_import, division, unicode_literals

# This is an automatically generated file. You can find more configuration
# parameters in 'config.py' file.

# The family of sites to work on by default.
#
# ‘site.py’ imports ‘families/xxx_family.py’, so if you want to change
# this variable, you need to use the name of one of the existing family files
# in that folder or write your own, custom family file.
#
# For ‘site.py’ to be able to read your custom family file, you must
# save it to ‘families/xxx_family.py’, where ‘xxx‘ is the codename of the
# family that your custom ‘xxx_family.py’ family file defines.
#
# You can also save your custom family files to a different folder. As long
# as you follow the ‘xxx_family.py’ naming convention, you can register your
# custom folder in this configuration file with the following global function:
#
#   register_families_folder(folder_path)
#
# Alternatively, you can register particular family files that do not need
# to follow the ‘xxx_family.py’ naming convention using the following
# global function:
#
#   register_family_file(family_name, file_path)
#
# Where ‘family_name’ is the family code (the ‘xxx’ in standard family file
# names) and ‘file_path’ is the absolute path to the target family file.
#
# If you use either of these functions to define the family to work on by
# default (the ‘family’ variable below), you must place the function call
# before the definition of the ‘family’ variable.
family = 'wikipedia'

# The language code of the site we're working on.
mylang = 'cs'

# The dictionary usernames should contain a username for each site where you
# have a bot account. If you have a unique username for all languages of a
# family , you can use '*'
usernames['wikipedia']['cs'] = u'Wesalius'

# The list of BotPasswords is saved in another file. Import it if needed.
# See https://www.mediawiki.org/wiki/Manual:Pywikibot/BotPasswords to know how
# use them.
password_file = "user-password.py"

# ############# LOGFILE SETTINGS ##############

# Defines for which scripts a logfile should be enabled. Logfiles will be
# saved in the 'logs' subdirectory.
#
# Example:
#     log = ['interwiki', 'weblinkchecker', 'table2wiki']
# It is also possible to enable logging for all scripts, using this line:
#     log = ['*']
# To disable all logging, use this:
#     log = []
# Per default, logging of interwiki.py is enabled because its logfiles can
# be used to generate so-called warnfiles.
# This setting can be overridden by the -log or -nolog command-line arguments.
log = ['interwiki']
# filename defaults to modulename-bot.log
logfilename = None
# maximal size of a logfile in kilobytes. If the size reached that limit the
# logfile will be renamed (if logfilecount is not 0) and the old file is filled
# again. logfilesize must be an integer value
logfilesize = 1024
# Number of rotating logfiles are created. The older files get the higher
# number. If logfilecount is 0, no logfile will be archived but the current
# logfile will be overwritten if the file size reached the logfilesize above.
# If logfilecount is -1 there are no rotating logfiles but the files where
# renamed if the logfile is full. The newest file gets the highest number until
# some logfiles where deleted.
logfilecount = 5
# set to 1 (or higher) to generate "informative" messages to terminal
verbose_output = 0
# set to True to fetch the pywiki version online
log_pywiki_repo_version = False
# if True, include a lot of debugging info in logfile
# (overrides log setting above)
debug_log = []

# ############# EXTERNAL SCRIPT PATH SETTINGS ##############
# Set your own script path to lookup for your script files.
#
# Your private script path must be located inside the
# framework folder, subfolders must be delimited by '.'.
# every folder must contain an (empty) __init__.py file.
#
# The search order is
# 1. user_script_paths in the given order
# 2. scripts
# 3. scripts/maintenance
# 4. scripts/archive
#
# sample:
# user_script_paths = ['scripts.myscripts']
user_script_paths = []

# ############# INTERWIKI SETTINGS ##############

# Should interwiki.py report warnings for missing links between foreign
# languages?
interwiki_backlink = True

# Should interwiki.py display every new link it discovers?
interwiki_shownew = True

# Should interwiki.py output a graph PNG file on conflicts?
# You need pydot for this:
# https://pypi.org/project/pydot/
interwiki_graph = False

# Specifies that the robot should process that amount of subjects at a time,
# only starting to load new pages in the original language when the total
# falls below that number. Default is to process (at least) 100 subjects at
# once.
interwiki_min_subjects = 100

# If interwiki graphs are enabled, which format(s) should be used?
# Supported formats include png, jpg, ps, and svg. See:
# http://www.graphviz.org/doc/info/output.html
# If you want to also dump the dot files, you can use this in your
# user-config.py:
# interwiki_graph_formats = ['dot', 'png']
# If you need a PNG image with an HTML image map, use this:
# interwiki_graph_formats = ['png', 'cmap']
# If you only need SVG images, use:
# interwiki_graph_formats = ['svg']
interwiki_graph_formats = ['png']

# You can post the contents of your autonomous_problems.dat to the wiki,
# e.g. to https://de.wikipedia.org/wiki/Wikipedia:Interwiki-Konflikte .
# This allows others to assist you in resolving interwiki problems.
# To help these people, you can upload the interwiki graphs to your
# webspace somewhere. Set the base URL here, e.g.:
# 'https://www.example.org/~yourname/interwiki-graphs/'
interwiki_graph_url = None

# Save file with local articles without interwikis.
without_interwiki = False

# Experimental feature:
# Store the page contents on disk (/cache/ directory) instead of loading
# them in RAM.
interwiki_contents_on_disk = False

# ############# SOLVE_DISAMBIGUATION SETTINGS ############
#
# Set disambiguation_comment[FAMILY][LANG] to a non-empty string to override
# the default edit comment for the solve_disambiguation bot.
#
# Use %s to represent the name of the disambiguation page being treated.
# Example:
#
# disambiguation_comment['wikipedia']['en'] = \
#    'Robot-assisted disambiguation ([[WP:DPL|you can help!]]): %s'

# Sorting order for alternatives. Set to True to ignore case for sorting order.
sort_ignore_case = False

# ############# IMAGE RELATED SETTINGS ##############
# If you set this to True, images will be uploaded to Wikimedia
# Commons by default.
upload_to_commons = False

# ############# SETTINGS TO AVOID SERVER OVERLOAD ##############

# Slow down the robot such that it never requests a second page within
# 'minthrottle' seconds. This can be lengthened if the server is slow,
# but never more than 'maxthrottle' seconds. However - if you are running
# more than one bot in parallel the times are lengthened.
#
# 'maxlag' is used to control the rate of server access (see below).
# Set minthrottle to non-zero to use a throttle on read access.
minthrottle = 0
maxthrottle = 60

# Slow down the robot such that it never makes a second page edit within
# 'put_throttle' seconds.
put_throttle = 10

# Sometimes you want to know when a delay is inserted. If a delay is larger
# than 'noisysleep' seconds, it is logged on the screen.
noisysleep = 3.0

# Defer bot edits during periods of database server lag. For details, see
# https://www.mediawiki.org/wiki/Maxlag_parameter
# You can set this variable to a number of seconds, or to None (or 0) to
# disable this behavior. Higher values are more aggressive in seeking
# access to the wiki.
# Non-Wikimedia wikis may or may not support this feature; for families
# that do not use it, it is recommended to set minthrottle (above) to
# at least 1 second.
maxlag = 5

# Maximum of pages which can be retrieved at one time from wiki server.
# -1 indicates limit by api restriction
step = -1

# Maximum number of times to retry an API request before quitting.
max_retries = 15
# Minimum time to wait before resubmitting a failed API request.
retry_wait = 5
# Maximum time to wait before resubmitting a failed API request.
retry_max = 120

# ############# TABLE CONVERSION BOT SETTINGS ##############

# Will split long paragraphs for better reading the source.
# Only table2wiki.py use it by now.
splitLongParagraphs = False
# sometimes HTML-tables are indented for better reading.
# That can do very ugly results.
deIndentTables = True

# ############# WEBLINK CHECKER SETTINGS ##############

# How many external links should weblinkchecker.py check at the same time?
# If you have a fast connection, you might want to increase this number so
# that slow servers won't slow you down.
max_external_links = 50

report_dead_links_on_talk = False

# Don't alert on links days_dead old or younger
weblink_dead_days = 7

# ############# DATABASE SETTINGS ##############
# Setting to connect the database or replica of the database of the wiki.
# db_name_format can be used to manipulate the dbName of site.
#
# Example for a pywikibot running on wmflabs:
# db_hostname = 'enwiki.analytics.db.svc.eqiad.wmflabs'
# db_name_format = '{0}_p'
# db_connect_file = user_home_path('replica.my.cnf')
db_hostname = 'localhost'
db_username = ''
db_password = ''
db_name_format = '{0}'
db_connect_file = user_home_path('.my.cnf')
# local port for mysql server
# ssh -L 4711:enwiki.analytics.db.svc.eqiad.wmflabs:3306 \
#     user@login.tools.wmflabs.org
db_port = 3306

# ############# SEARCH ENGINE SETTINGS ##############
# Live search web service appid settings.
#
# Yahoo! Search Web Services are not operational.
# See https://phabricator.wikimedia.org/T106085
yahoo_appid = ''

# To use Windows Live Search web service you must get an AppID from
# http://www.bing.com/dev/en-us/dev-center
msn_appid = ''

# ############# FLICKR RIPPER SETTINGS ##############

# Using the Flickr api
flickr = {
    'api_key': '',  # Provide your key!
    'api_secret': '',  # Api secret of your key (optional)
    'review': False,  # Do we use automatically make our uploads reviewed?
    'reviewer': '',  # If so, under what reviewer name?
}

# ############# COPYRIGHT SETTINGS ##############

# Enable/disable search engine in copyright.py script
copyright_google = True
copyright_yahoo = True
copyright_msn = False

# Perform a deep check, loading URLs to search if 'Wikipedia' is present.
# This may be useful to increase the number of correct results. If you haven't
# a fast connection, you might want to keep them disabled.
copyright_check_in_source_google = False
copyright_check_in_source_yahoo = False
copyright_check_in_source_msn = False

# Web pages may contain a Wikipedia text without the word 'Wikipedia' but with
# the typical '[edit]' tag as a result of a copy & paste procedure. You want
# no report for this kind of URLs, even if they are copyright violations.
# However, when enabled, these URLs are logged in a file.
copyright_check_in_source_section_names = False

# Limit number of queries for page.
copyright_max_query_for_page = 25

# Skip a specified number of queries
copyright_skip_query = 0

# Number of attempts on connection error.
copyright_connection_tries = 10

# Behavior if an exceeded error occur.
#
# Possibilities:
#
#    0 = None
#    1 = Disable search engine
#    2 = Sleep (default)
#    3 = Stop
copyright_exceeded_in_queries = 2
copyright_exceeded_in_queries_sleep_hours = 6

# Append last modified date of URL to script result
copyright_show_date = True

# Append length of URL to script result
copyright_show_length = True

# By default the script tries to identify and skip text that contains a large
# comma separated list or only numbers. But sometimes that might be the
# only part unmodified of a slightly edited and not otherwise reported
# copyright violation. You can disable this feature to try to increase the
# number of results.
copyright_economize_query = True

# ############# HTTP SETTINGS ##############
# Use a persistent http connection. An http connection has to be established
# only once per site object, making stuff a whole lot faster. Do NOT EVER
# use this if you share Site objects across threads without proper locking.
#
# DISABLED FUNCTION. Setting this variable will not have any effect.
persistent_http = False

# Default socket timeout in seconds.
# DO NOT set to None to disable timeouts. Otherwise this may freeze your
# script.
# You may assign either a tuple of two int or float values for connection and
# read timeout, or a single value for both in a tuple (since requests 2.4.0).
socket_timeout = (6.05, 45)


# ############# COSMETIC CHANGES SETTINGS ##############
# The bot can make some additional changes to each page it edits, e.g. fix
# whitespace or positioning of interwiki and category links.

# This is an experimental feature; handle with care and consider re-checking
# each bot edit if enabling this!
cosmetic_changes = False

# If cosmetic changes are switched on, and you also have several accounts at
# projects where you're not familiar with the local conventions, you probably
# only want the bot to do cosmetic changes on your "home" wiki which you
# specified in config.mylang and config.family.
# If you want the bot to also do cosmetic changes when editing a page on a
# foreign wiki, set cosmetic_changes_mylang_only to False, but be careful!
cosmetic_changes_mylang_only = True

# The dictionary cosmetic_changes_enable should contain a tuple of languages
# for each site where you wish to enable in addition to your own langlanguage
# (if cosmetic_changes_mylang_only is set)
# Please set your dictionary by adding such lines to your user-config.py:
# cosmetic_changes_enable['wikipedia'] = ('de', 'en', 'fr')
cosmetic_changes_enable = {}

# The dictionary cosmetic_changes_disable should contain a tuple of languages
# for each site where you wish to disable cosmetic changes. You may use it with
# cosmetic_changes_mylang_only is False, but you can also disable your own
# language. This also overrides the settings in the cosmetic_changes_enable
# dictionary. Please set your dict by adding such lines to your user-config.py:
# cosmetic_changes_disable['wikipedia'] = ('de', 'en', 'fr')
cosmetic_changes_disable = {}

# cosmetic_changes_deny_script is a list of scripts for which cosmetic changes
# are disabled. You may add additional scripts by appending script names in
# your user-config.py ("+=" operator is strictly recommended):
# cosmetic_changes_deny_script += ['your_script_name_1', 'your_script_name_2']
# Appending the script name also works:
# cosmetic_changes_deny_script.append('your_script_name')
cosmetic_changes_deny_script = ['category_redirect', 'cosmetic_changes',
                                'newitem', 'touch']

# ############# REPLICATION BOT SETTINGS ################
# You can add replicate_replace to your user-config.py.
#
# Use has the following format:
#
# replicate_replace = {
#            'wikipedia:li': {'Hoofdpagina': 'Veurblaad'}
# }
#
# to replace all occurrences of 'Hoofdpagina' with 'Veurblaad' when writing to
# liwiki. Note that this does not take the origin wiki into account.
replicate_replace = {}

# ############# FURTHER SETTINGS ##############

# Proxy configuration

# TODO: proxy support
proxy = None

# Simulate settings

# Defines what additional actions the bots are NOT allowed to do (e.g. 'edit')
# on the wiki server. Allows simulation runs of bots to be carried out without
# changing any page on the server side. Use this setting to add more actions
# in user-config.py for wikis with extra write actions.
actions_to_block = []

# Set simulate to True or use -simulate option to block all actions given
# above.
simulate = False

# How many pages should be put to a queue in asynchronous mode.
# If maxsize is <= 0, the queue size is infinite.
# Increasing this value will increase memory space but could speed up
# processing. As higher this value this effect will decrease.
max_queue_size = 64

# Define the line separator. Pages retrieved via API have "\n" whereas
# pages fetched from screen (mostly) have "\r\n". Interwiki and category
# separator settings in family files should use multiplied of this.
# LS is a shortcut alias.
line_separator = LS = '\n'

# Settings to enable mwparserfromhell
# <https://mwparserfromhell.readthedocs.org/en/latest/>
# Currently used in textlib.extract_templates_and_params
# This is more accurate than our current regex, but only works
# if the user has already installed the library.
use_mwparserfromhell = True

# Pickle protocol version to use for storing dumps.
# This config variable is not used for loading dumps.
# Version 2 is common to both Python 2 and 3, and should
# be used when dumps are accessed by both versions.
# Version 4 is only available for Python 3.4
pickle_protocol = 2

ERROR: Username for test:test is undefined.

usernames['wikipedia']['cs'] = u'Wesalius'

@Wesalius: Your bot is running on site test:test but you defined a user for wikipedia:cs only.

Try to remove pywikibot.lwp file and try it again. I do not see any problem in your user-config.py at first sight. Also check if there is nothing wrong with your user-password.py. If nothing helps, you could also try to generate new user-config.py or download/clone new clean Pywikibot folder too.

If nothing helps anyway, there could be a problem on the Pywikibot site, but I could not reproduce your issue today.

I think it's loading a wrong user-config.py or something...

ERROR: Username for test:test is undefined.

usernames['wikipedia']['cs'] = u'Wesalius'

@Wesalius: Your bot is running on site test:test but you defined a user for wikipedia:cs only.

How do I tell pwb to use different site then? Maybe a new "feature" I am not aware of, but I did a clean install yesterday and in the past I had never have to define anything beside telling pwb in generate_user_files what site and what language I want to use while editing.

I think it's loading a wrong user-config.py or something...

Thats what I thought too... I deleted the one I had and generated a new one to be sure, same story...

Try to remove pywikibot.lwp file and try it again. I do not see any problem in your user-config.py at first sight. Also check if there is nothing wrong with your user-password.py. If nothing helps, you could also try to generate new user-config.py or download/clone new clean Pywikibot folder too.

If nothing helps anyway, there could be a problem on the Pywikibot site, but I could not reproduce your issue today.

Thank you for your suggestion, I will try those steps some time this week and report back.

I can reproduce it with the following traceback:

C:\pwb\GIT\core>pwb.py touch -page:user:xqt/Test
family and mylang are not set.
Defaulting to family='test' and mylang='test'.
Traceback (most recent call last):
  File "C:\pwb\GIT\core\pywikibot\login.py", line 112, in __init__
    self.username = self.username or family_usernames['*']
KeyError: '*'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\pwb\GIT\core\pwb.py", line 257, in <module>
    if not main():
  File "C:\pwb\GIT\core\pwb.py", line 250, in main
    run_python_file(filename, [filename] + args, argvu, file_package)
  File "C:\pwb\GIT\core\pwb.py", line 119, in run_python_file
    main_mod.__dict__)
  File ".\scripts\touch.py", line 133, in <module>
    main()
  File ".\scripts\touch.py", line 124, in main
    pywikibot.Site().login()
  File "C:\pwb\GIT\core\pywikibot\site.py", line 2123, in login
    site=self, sysop=sysop, user=self._username[sysop])
  File "C:\pwb\GIT\core\pywikibot\tools\__init__.py", line 1737, in wrapper
    return obj(*__args, **__kw)
  File "C:\pwb\GIT\core\pywikibot\login.py", line 120, in __init__
    'wiki_code': self.site.code})
pywikibot.exceptions.NoUsername:  ERROR: Username for test:test is undefined.
If you have an account for that site, please add a line to user-config.py:

usernames['test']['test'] = 'myUsername'
CRITICAL: Exiting due to uncaught exception <class 'pywikibot.exceptions.NoUsern
ame'>

C:\pwb\GIT\core>

Seems an pywikibot environment variable 'PYWIKIBOT_NO_USER_CONFIG' or 'PYWIKIBOT2_NO_USER_CONFIG' is set.

@Wesalius: could you please provide the whole traceback including the command line or use touch.py like me:
pwb.py touch -page:user:Wesalius. Please also check the environment variables using pwb shell:

pwb.py shell
>>> from os import environ
>>> sorted(environ.keys())
['ALLUSERSPROFILE', 'APPDATA', 'ASL.LOG', 'AUTINSTLOG', 'COMMONPROGRAMFILES',
...
'PROGRAMW6432', 'PROMPT', 'PSMODULEPATH', 'PUBLIC', 'PYWIKIBOT_DIR_PWB', 'S7TMP', 'SESSIONNAME', 
...
'USERPROFILE', 'WINDIR', 'WINDOWS_TRACING_FLAGS', 'WINDOWS_TRACING_LOGFILE']

Also provide the complete version.py result

Resolved with setting correct permissions to user-config.py. The file has to be only readable. The generate-user-files.py produces a 777 user-config.py file.

python pwb.py generate-user-files
....
stat --format '%a' user-config.py
777

After changing the permissions to 400 (for example) it proceeds normally.

If this is explicitly stated somewhere, then I am sorry I missed it and bothered you.


I guess its not needed anymore, but I generated the data requested by @Xqt, so here they are

version.py:

Pywikibot: [https] wikimedia-pywikibot.git (8d70cc4, g10542, 2018/12/27, 11:00:35, OUTDATED)
Release version: 3.1.dev0
requests version: 2.21.0
  cacerts: /home/wesalius/.local/lib/python3.5/site-packages/certifi/cacert.pem
    certificate test: ok
Python: 3.5.3 (default, Sep 27 2018, 17:25:39)
[GCC 6.3.0 20170516]
PYWIKIBOT_DIR: Not set
PYWIKIBOT_DIR_PWB:
PYWIKIBOT_NO_USER_CONFIG: Not set
Config base dir: /mnt/c/Users/wesalius/Desktop/core/pywikibot
Usernames for family "wikipedia":
        cs: Wesalius (no sysop configured)

Enviroment variables:

>>> sorted(environ.keys())
['EDITOR', 'HOME', 'HOSTTYPE', 'LANG', 'LOGNAME', 'NAME', 'PATH', 'PWD', 'PYWIKIBOT_DIR_PWB', 'SHELL', 'SHLVL', 'TERM', 'USER', 'VISUAL', 'WSLENV', '_']
Xqt triaged this task as Medium priority.Jan 4 2019, 6:23 PM

I didn’t know this behaviour. This is a Linux issue and it should be documented inside the script or better solved by it. It seems that pywikibot can open this file but cannot read its content. I am not familiar with Linux and cannot verify my assumption.

@Wesalius: btw thanks for investigating in this task :)

Xqt renamed this task from Exception - No username to user-config.py with mode 777 is not readable.Jan 4 2019, 6:27 PM

@Wesalius Then there are two possibilities:
a) you have bot.py, generate_user_files.py, pwb.py or config2.py in 777 and the user-config.py is created by those files with inherited permissions: you should reset permissions for these files (to 644, ideally for all Pywikibot files)
b) your (file)system defaults new files to 777: there is nothing we can do with this, you can try to change it somehow

@Wesalius Then there are two possibilities:
a) you have bot.py, generate_user_files.py, pwb.py or config2.py in 777 and the user-config.py is created by those files with inherited permissions: you should reset permissions for these files (to 644, ideally for all Pywikibot files)
b) your (file)system defaults new files to 777: there is nothing we can do with this, you can try to change it somehow

There is nothing I personally need done about it, I will remember it, its just a thing that another linux/wsl user might bump into (I did a clean install, no tweaking) , so it would be wise to document it somehow to prevent future problems.

it would be wise to document it somehow to prevent future problems.

Either this or the generating script should print an appropriate message (or both)

mode 777 being un-readable is not POSIX-conformant and is not Linux bahavior. filesystem default to 777 is also not Linux bahavior (which is mode to open(2) - umask).

The paths in the traceback (/mnt/c/) looks like Windows Subsystem for Linux, and I suspect NTFS ACLs are at play here; I don't have a easily-testable windows setup ready so I cannot test this.

Though, POSIX ACLs might be able to prevent reading 777 files; I have not looked into that. However, POSIX ACLs should not be 'enabled' for a clean install, and even if it's 'enabled' ls should show clearly that the file has ACLs.

Could it be https://github.com/wikimedia/pywikibot/blob/e57dbff2bf6d4dd719a6f576d96a3b285acbc4ea/pywikibot/config2.py#L1054:

if OSWIN32 or _filemode & 0o02 == 0:
    with open(_filename, 'rb') as f:
        exec(compile(f.read(), _filename, 'exec'), _uc)
else:
    warning("Skipped '%(fn)s': writeable by others."
            % {'fn': _filename})

oh, os.open default mode is 777. Why doesn't WSL have a sane umask?

zhuyifei1999 renamed this task from user-config.py with mode 777 is not readable to generate_user_files creates user-config.py with mode 777 on WSL, and then pywikibot refuse to load the config for security.Jan 5 2019, 12:39 PM

In generate_user_config.py we use codecs.open(), but I think they work the same. Yeah, I also suspected Windows, as the only possible permission for files coming from Windows is 777. We are triggering warning, maybe we should try to change permissions before we throw the warning? (if possible - on NTFS drives all files can be 777 only. That's why WSL's umask probably isn't the umask are used to, but some Microsoft's modified version)

Yeah, I also suspected Windows, as the only possible permission for files coming from Windows is 777.

Ummm.. not really?

We are triggering warning, maybe we should try to change permissions before we throw the warning?

From a stricter security standpoint, if the file is chmodded badly the contents is not trusted. It needs to be manually inspected immediately after chmodded to a securer mode.
(From an even stricter security standpoint, if the file is chmodded badly the file inode must be discarded. There's no telling how many random hackers have already opened the file and will keep their privileges even after chmodding to a restricted value. But that's for Linux, not sure about WSL.)

Yeah, I also suspected Windows, as the only possible permission for files coming from Windows is 777.

Ummm.. not really?

I meant Windows, not WSL. On WSL I already said they modify permission handling, so ... noone really know (but I think they are pushing the code somewhere publicly?)